#pragma once
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <queue>
#include "Thread.hpp"
#include "Mutex.hpp"
#include <mutex>

using namespace ThreadNs;
#define NUM 10

template <class T>
class ThreadPool;

// 对线程库封装
template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *tp = nullptr, const string &name = nullptr) : _threadpool(tp), _name(name)
    {
    }

public:
    ThreadPool<T> *_threadpool;
    string _name;
};

template <class T>
class ThreadPool
{
private:
    static void *handlertask(void *args)
    {
        ThreadData<T> *td = (ThreadData<T> *)args;
        while (true)
        {
            // 处理
            T t;
            {
                lockguard lock(&(td->_threadpool->_mutex)); // raii锁
                while (td->_threadpool->isemptyqueue())
                {
                    td->_threadpool->waitqueue();
                }
                // pop的本质就是，将任务从公共队列中，拿到当前线程独立的栈中
                t = td->_threadpool->pop();
                // td->threadpool->unlockqueue();
                // t(); // bug,这里的任务要到临界区外面来处理
            }
            t();
        }
        delete td;
        return nullptr;
    }

    ThreadPool(const int &num = NUM) : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        // 将所有在休眠线程插入到vector
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(new Thread());
        }
    }

    void operator=(const ThreadPool &) = delete; // 去掉赋值语句
    ThreadPool(const ThreadPool &) = delete;

public:
    void lockqueue() { pthread_mutex_lock(&_mutex); }
    void unlockqueue() { pthread_mutex_unlock(&_mutex); }
    bool isemptyqueue() { return _task_queue.empty(); }
    void waitqueue() { pthread_cond_wait(&_cond, &_mutex); }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

public:
    // 回调
    void run()
    {
        for (const auto &e : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, e->threadname());
            e->start(handlertask, td);
            cout << e->threadname() << "已经启动" << endl;
        }
    }

    void push(const T &in)
    {
        // 上锁
        lockguard lock(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    void pop(T *out)
    {
        lockguard lock(&_mutex);

        out = _task_queue.pop();
        pthread_cond_signal(&_cond);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &e : _threads)
        {
            delete e;
        }
    }

    // 成员方法是可以直接访问静态成员的
    static ThreadPool<T> *getInstance()
    {
        if (tp == nullptr)
        {
            _singlock.lock();
            if (tp == nullptr)
            {
                tp = new ThreadPool<T>();
            }
            _singlock.unlock();
        }

        return tp;
    }

public:
    int _num;                       // 线程在数量
    std::vector<Thread *> _threads; // 线程都放到这里
    queue<T> _task_queue;           // 任务队列
    pthread_mutex_t _mutex;         // 锁
    pthread_cond_t _cond;           // 条件变量

    static ThreadPool<T> *tp; // 静态指针
    static mutex _singlock;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::tp = nullptr; // 初始化

template <class T>
mutex ThreadPool<T>::_singlock;
